﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace EmbeddedLanguage
{
    public class PropBinder<T>
    {
        public T Val;

        //public T InitialVal;

        public static T operator ~(PropBinder<T> prop)
        {
            if (prop == null) return default(T);
            return prop.Val;
        }

        public static T operator | (PropBinder<T> prop, T defaultValue)
        {
            if (prop == null) return defaultValue;
            return prop.Val;
        }

        public static PropBinder<T> operator & (T NewValue, PropBinder<T> prop)
        {
            PropBinder<T> binder = prop == null ? new PropBinder<T>() : prop;
            if (binder.Val.Eq(NewValue)) return binder;
            binder.Val = NewValue;
            return binder;
        }

        //public static PropBinder<T> operator >(PropBinder<T> prop, T NewValue)
        //{
        //    PropBinder<T> binder = prop == null ? new PropBinder<T>() : prop;
        //    if (binder.Val.Eq(NewValue)) return binder;
        //    binder.Val = NewValue;
        //    return binder;
        //}
    }

    public static class PropBinderEx
    {
        public static T GetVal<T>(this PropBinder<T> binder, T InitialValue)
        {
            return binder | InitialValue;
        }

        //TODO:  operator override?

        public static PropBinder<T> eq<T>(this PropBinder<T> binder, T NewVal)
        {
            return eq<T>(binder, NewVal, default(T), null, null);
        }

        public static PropBinder<T> eq<T>(this PropBinder<T> binder, T NewVal, T InitialValue,
            Action<PropBinder<T>> PutIfNull, Action ActionIfInvalid){
                if (binder == null)
                {
                    if (NewVal.Eq(InitialValue)) return null;
                    var newBinder = new PropBinder<T>
                    {
                        Val = NewVal,
                    };
                    if(PutIfNull != null) PutIfNull(newBinder);
                    return newBinder;
                }
                else
                {
                    binder.Val = NewVal;
                    
                }
                return binder;
        }

        public static bool Eq<T>(this T LHS, T RHS)
        {
            if (LHS == null)
            {
                if (RHS == null) return true;
            }
            else
            {
                if (RHS == null) return false;
            }
            #region Neither LHS nor RHS is null
            return LHS.Equals(RHS);
            #endregion
        }
    }
}
